#include <sys/epoll.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <vector>

class Epoll
{
public:
   Epoll()
      :_epFd(-1)
   {
      _epFd = epoll_create(1);
      if (_epFd < 0) {
	 std::cerr << "Epoll::Epoll()::epoll_create err..." << std::endl;
      } 
   }

   bool Add(int fd, int events)
   {
      struct epoll_event eve;
      bzero(&eve, sizeof(eve));
      eve.events = events;
      eve.data.fd = fd;
      if (epoll_ctl(_epFd, EPOLL_CTL_ADD, fd, &eve) < 0) {
	 std::cerr << "Epoll::Add::epoll_ctl err..." << std::endl;
	 return false;
      }
      return true;
   }

   bool Modify(int fd, int events)
   {
      struct epoll_event eve;
      bzero(&eve, sizeof(eve));
      eve.events = events;
      eve.data.fd = fd;
      if (epoll_ctl(_epFd, EPOLL_CTL_MOD, fd, &eve) < 0) {
	 std::cerr << "Epoll::Modify::epoll_ctl err..." << std::endl;
	 return false;
      }
      return true;
   }

   bool Delete(int fd)
   {
      if (epoll_ctl(_epFd, EPOLL_CTL_DEL, fd, nullptr) < 0) {
	 std::cerr << "Epoll::Delete::epoll_ctl err..." << std::endl;
	 return false;
      }
      return true;
   }

   bool Wait(std::vector<int>* ready)
   {
      struct epoll_event rEvents[100] = { 0 };
      int nFds = epoll_wait(_epFd, rEvents, sizeof(rEvents) / sizeof(rEvents[0]), 1000);
      if (nFds < 0) {
	 std::cerr << "Epoll::Wait::epoll_wait err..." << std::endl;
	 return false;
      }
      else if (nFds == 0) {
	 std::cout << "timeout..." << std::endl;
	 return false;
      }
      else {
	 for (int i = 0; i < nFds; ++i) {
	    ready->push_back(rEvents[i].data.fd);
	 }
      }
      return true;
   }

   ~Epoll()
   {
      close(_epFd);
      _epFd = -1;
   }

private:
   int _epFd;
};
